package com.csun.cmny.provider.service.impl;

import com.csun.cmny.base.dto.LoginAuthDto;
import com.csun.cmny.base.enums.ErrorCodeEnum;
import com.csun.cmny.core.support.BaseService;
import com.csun.cmny.provider.dao.DmcCsunBodySensorLocationMapper;
import com.csun.cmny.provider.device.csun.gateway.GatewayMessageSender;
import com.csun.cmny.provider.device.csun.gateway.entity.CsunGatewayData;
import com.csun.cmny.provider.exceptions.DmcBizException;
import com.csun.cmny.provider.model.constant.DeviceConstant;
import com.csun.cmny.provider.model.domain.*;
import com.csun.cmny.provider.model.dto.bodysensor.BindCsunBodySensorLocationDto;
import com.csun.cmny.provider.model.dto.bodysensor.CsunBodySensorPageQuery;
import com.csun.cmny.provider.model.dto.propertyManagement.SelectDeviceDataDto;
import com.csun.cmny.provider.model.enums.bodysensor.DmcCsunBodySensorBindTypeEnum;
import com.csun.cmny.provider.model.enums.device.DmcDeviceTypeEnum;
import com.csun.cmny.provider.model.vo.BodySensorReqVo;
import com.csun.cmny.provider.model.vo.RoomBuildingVo;
import com.csun.cmny.provider.model.vo.csunbody.DmcCsunBodySensorVo;
import com.csun.cmny.provider.model.vo.life.DmcDeviceByRoom;
import com.csun.cmny.provider.model.vo.propertyManagement.PropertyDataVo;
import com.csun.cmny.provider.resolver.CmnyMessageSource;
import com.csun.cmny.provider.service.*;
import com.csun.cmny.util.PubUtils;
import com.csun.cmny.util.PublicUtil;
import com.csun.cmny.util.RedisKeyUtil;
import com.csun.cmny.util.RedisUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.base.Preconditions;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisConnectionUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

/**
 * @Auther: chisj chisj@foxmal.com
 * @Date: 2019-02-11 20:08
 * @Description: the class dmc csun body sensor location service impl
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class DmcCsunBodySensorLocationServiceImpl extends BaseService<DmcCsunBodySensorLocation>
        implements DmcCsunBodySensorLocationService {

    @Resource
    private OmcRpcService omcRpcService;
    @Resource
    private DmcDeviceService dmcDeviceService;
    @Resource
    private CmnyMessageSource cmnyMessageSource;
    @Resource
    private DmcDeviceAlertService dmcDeviceAlertService;
    @Resource
    private DmcCsunBodySensorLocationMapper dmcCsunBodySensorLocationMapper;
    @Resource
    private DmcCsunBodySensorConfigService dmcCsunBodySensorConfigService;
    @Resource
    private DmcCsunGatewayConfigBodySensorService dmcCsunGatewayConfigBodySensorService;
    @Resource
    private GatewayMessageSender gatewayMessageSender;
    @Resource
    private DmcCsunGatewayBindService dmcCsunGatewayBindService;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private DmcCsunBodyGroupBindService dmcCsunBodyGroupBindService;


    /**
     * bind csun body sensor location
     *
     * @param bindCsunBodySensorLocationDto bind csun body sensor location dto
     * @param loginAuthDto                  login auth dto
     *
     * @return the int.
     */
    @Override
    public Integer bindCsunBodySensorLocation(BindCsunBodySensorLocationDto bindCsunBodySensorLocationDto,
                                              LoginAuthDto loginAuthDto) {

        // 1.校验人体感应
        DmcDevice dmcDevice = dmcDeviceService
                .checkDeviceIsCsunBodySensorByDeviceId(bindCsunBodySensorLocationDto.getDeviceId());
        if (PublicUtil.isEmpty(dmcDevice)) {
            throw new DmcBizException(ErrorCodeEnum.DMC100610027, bindCsunBodySensorLocationDto.getDeviceId());
        }

        // 2.校验人体感应是否已经被绑定
        DmcCsunBodySensorLocation dmcCsunBodySensorLocationQuery = dmcCsunBodySensorLocationMapper
                .selectByPrimaryKey(bindCsunBodySensorLocationDto.getDeviceId());
        if (PublicUtil.isNotEmpty(dmcCsunBodySensorLocationQuery)) {
            throw new DmcBizException(ErrorCodeEnum.DMC100610028, dmcCsunBodySensorLocationQuery.getDeviceId(),
                    dmcCsunBodySensorLocationQuery.getLocation());
        }

        // 3.校验绑定类型
        Preconditions.checkArgument(!PubUtils.isNull(bindCsunBodySensorLocationDto.getBindType()),
                cmnyMessageSource.getMessage("csun.body.sensor.location.bind.type.null", null));

        Preconditions.checkArgument(bindCsunBodySensorLocationDto.getBindType() >= 0
                        && bindCsunBodySensorLocationDto.getBindType() <= 4,
                cmnyMessageSource.getMessage("csun.body.sensor.location.bind.type.range", null));

        // 4.校验位置
        Preconditions.checkArgument(!PubUtils.isNull(bindCsunBodySensorLocationDto.getLocation()),
                cmnyMessageSource.getMessage("csun.body.sensor.location.null", null));

        // 5.校验房间Id
        if (bindCsunBodySensorLocationDto.getBindType().equals(DmcCsunBodySensorBindTypeEnum.CUSTOM.getKey())) {

            /*
             * 2020-01-10
             * */
            // 删除已经下发的配置
            DmcCsunGatewayConfigBodySensor dmcCsunGatewayConfigBodySensor = new DmcCsunGatewayConfigBodySensor();
            dmcCsunGatewayConfigBodySensor.setDeviceId(bindCsunBodySensorLocationDto.getDeviceId());
            dmcCsunGatewayConfigBodySensorService.delete(dmcCsunGatewayConfigBodySensor);

            // 查询配置
            DmcCsunBodySensorConfig dmcCsunBodySensorConfig = dmcCsunBodySensorConfigService
                    .queryConfigByRoomIdAndGroupId(bindCsunBodySensorLocationDto.getDeviceId(),
                            0, dmcDevice.getGroupId());
            // TODO 设置配置

            // 发送配置
            if (PublicUtil.isNotEmpty(dmcCsunBodySensorConfig)) {
                gatewayMessageSender.setLifeBodySensorTimer(bindCsunBodySensorLocationDto.getDeviceId().toString(),
                        dmcCsunBodySensorConfig.getToiletAttentionTime().toString(), dmcCsunBodySensorConfig.getToiletWarningTime().toString(), dmcCsunBodySensorConfig.getToiletUnusualTime().toString());
            }
        }
        if (bindCsunBodySensorLocationDto.getBindType().equals(DmcCsunBodySensorBindTypeEnum.ROOM.getKey())) {
            // 绑定类型为房间
            Preconditions.checkArgument(!PubUtils.isNull(bindCsunBodySensorLocationDto.getRoomId()),
                    cmnyMessageSource.getMessage("csun.body.sensor.location.bind.room.id.null", null));
            // 校验房间Id是否存在
            // TODO 校验房间Id是否存在
            RoomBuildingVo roomBuildingVo = omcRpcService
                    .queryRoomBuildingByRoomId(bindCsunBodySensorLocationDto.getRoomId());
            if (PublicUtil.isEmpty(roomBuildingVo)) {
                // 房间不存在
                throw new DmcBizException(ErrorCodeEnum.DMC100610058);
            }
            bindCsunBodySensorLocationDto.setLocation(roomBuildingVo.getLocation());

            DmcCsunGatewayConfigBodySensor dmcCsunGatewayConfigBodySensor = new DmcCsunGatewayConfigBodySensor();
            dmcCsunGatewayConfigBodySensor.setDeviceId(bindCsunBodySensorLocationDto.getDeviceId());
            dmcCsunGatewayConfigBodySensorService.delete(dmcCsunGatewayConfigBodySensor);

            // 查询配置
            DmcCsunBodySensorConfig dmcCsunBodySensorConfig = dmcCsunBodySensorConfigService
                    .queryConfigByRoomIdAndGroupId(bindCsunBodySensorLocationDto.getDeviceId(),bindCsunBodySensorLocationDto.getRoomId(),dmcDevice.getGroupId());
            // TODO 设置配置

            // 发送配置
            if (PublicUtil.isNotEmpty(dmcCsunBodySensorConfig)) {
                gatewayMessageSender.setLifeBodySensorTimer(bindCsunBodySensorLocationDto.getDeviceId().toString(),
                        dmcCsunBodySensorConfig.getToiletAttentionTime().toString(), dmcCsunBodySensorConfig.getToiletWarningTime().toString(), dmcCsunBodySensorConfig.getToiletUnusualTime().toString());
            }
            bindCsunBodySensorLocationDto.setLocation(roomBuildingVo.getLocation());
        }

        // 5.校验房间Id
        if (bindCsunBodySensorLocationDto.getBindType().equals(DmcCsunBodySensorBindTypeEnum.LIFE_ROOM.getKey())) {
            // 绑定类型为房间
            Preconditions.checkArgument(!PubUtils.isNull(bindCsunBodySensorLocationDto.getRoomId()),
                    cmnyMessageSource.getMessage("csun.body.sensor.location.bind.room.id.null", null));
            // 校验房间Id是否存在
            // TODO 校验房间Id是否存在
            RoomBuildingVo roomBuildingVo = omcRpcService
                    .queryRoomBuildingByRoomId(bindCsunBodySensorLocationDto.getRoomId());
            if (PublicUtil.isEmpty(roomBuildingVo)) {
                // 房间不存在
                throw new DmcBizException(ErrorCodeEnum.DMC100610058);
            }

            /*
            * 2020-01-10
            * */
            // 删除已经下发的配置
            DmcCsunGatewayConfigBodySensor dmcCsunGatewayConfigBodySensor = new DmcCsunGatewayConfigBodySensor();
            dmcCsunGatewayConfigBodySensor.setDeviceId(bindCsunBodySensorLocationDto.getDeviceId());
            dmcCsunGatewayConfigBodySensorService.delete(dmcCsunGatewayConfigBodySensor);

            // 查询配置
            DmcCsunBodySensorConfig dmcCsunBodySensorConfig = dmcCsunBodySensorConfigService
                    .queryConfigByRoomIdAndGroupId(bindCsunBodySensorLocationDto.getDeviceId(),bindCsunBodySensorLocationDto.getRoomId(),dmcDevice.getGroupId());
            // TODO 设置配置

            // 发送配置
            if (PublicUtil.isNotEmpty(dmcCsunBodySensorConfig)) {
                gatewayMessageSender.setLifeBodySensorTimer(bindCsunBodySensorLocationDto.getDeviceId().toString(),
                        dmcCsunBodySensorConfig.getToiletAttentionTime().toString(), dmcCsunBodySensorConfig.getToiletWarningTime().toString(), dmcCsunBodySensorConfig.getToiletUnusualTime().toString());
            }
            bindCsunBodySensorLocationDto.setLocation(roomBuildingVo.getLocation());
        }

        // 6.添加绑定
        DmcCsunBodySensorLocation dmcCsunBodySensorLocation = new DmcCsunBodySensorLocation();
        BeanUtils.copyProperties(bindCsunBodySensorLocationDto, dmcCsunBodySensorLocation);
        dmcCsunBodySensorLocation.setUpdateInfo(loginAuthDto);

        Integer result = dmcCsunBodySensorLocationMapper.insertSelective(dmcCsunBodySensorLocation);

        return result;
    }

    /**
     * break csun body sensor location
     *
     * @param deviceId device id
     * @return the int.
     */
    @Override
    public Integer breakCsunBodySensorLocation(Long deviceId) {

        // 1.判断设备Id是否存在
        DmcDevice dmcDevice = dmcDeviceService.checkDeviceIsCsunBodySensorByDeviceId(deviceId);
        if (PublicUtil.isEmpty(dmcDevice)) {
            throw new DmcBizException(ErrorCodeEnum.DMC100610027, deviceId);
        }

        // 2.判断人体感应是否已经绑定
        DmcCsunBodySensorLocation dmcCsunBodySensorLocationQuery = dmcCsunBodySensorLocationMapper
                .selectByPrimaryKey(deviceId);
        if (PublicUtil.isEmpty(dmcCsunBodySensorLocationQuery)) {
            throw new DmcBizException(ErrorCodeEnum.DMC100610029, deviceId);
        }

        // 判断是否绑定了人感组
        DmcCsunBodyGroupBind dmcCsunBodyGroupBind = new DmcCsunBodyGroupBind();
        dmcCsunBodyGroupBind.setDeviceId(deviceId);
        int count = dmcCsunBodyGroupBindService.selectCount(dmcCsunBodyGroupBind);
        if (count > 0) {
            throw new DmcBizException(ErrorCodeEnum.DMC100614012);
        }

        // 3.解绑人体感应
        Integer result = dmcCsunBodySensorLocationMapper.deleteByPrimaryKey(deviceId);
        if (result > 0) {

//            if(dmcCsunBodySensorLocationQuery.getBindType().equals(DeviceConstant.DEVICE_BIND_TYPE_LIFE)){
                dmcDeviceAlertService.deleteByDeviceId(deviceId);
//            }

            //删除人感配置
            dmcCsunBodySensorConfigService.deleteByKey(deviceId);
            //删除redis中的是否在房间的状态
            redisTemplate.delete(RedisKeyUtil.getCsunBodySensorIsInRoomKey(dmcDevice.getDeviceNo()));
        }

        return result;
    }

    /**
     * query csun body sensor list page
     *
     * @param csunBodySensorPageQuery csun body sensor page query
     * @return the page info.
     */
    @Override
    public PageInfo queryGroupBodySensorListWithPage(CsunBodySensorPageQuery csunBodySensorPageQuery) {

        PageHelper.startPage(csunBodySensorPageQuery.getPageNum(), csunBodySensorPageQuery.getPageSize());

        List<DmcCsunBodySensorVo> dmcCsunBodySensorVoList = dmcCsunBodySensorLocationMapper
                .queryGroupBodySensorListWithPage(csunBodySensorPageQuery);

        /*
         * @date 2020-3-12
         * @author wfb
         * @desc 新增是否在线状态*/

        for (DmcCsunBodySensorVo dmcCsunBodySensorVo : dmcCsunBodySensorVoList) {


            if(PublicUtil.isNotEmpty(dmcCsunBodySensorVo.getBindType())){
                Boolean aBoolean = redisTemplate.hasKey(RedisKeyUtil.getCsunBodySensorOnline(dmcCsunBodySensorVo.getDeviceNo()));
                if(aBoolean){
                    dmcCsunBodySensorVo.setStatus("online");
                }else {
                    dmcCsunBodySensorVo.setStatus("offline");
                }

            }
            }

        return new PageInfo<>(dmcCsunBodySensorVoList);
    }

    /**
     * get csun body sensor by device id
     *
     * @param deviceId device id
     * @return dmc csun body sensor vo
     */
    @Override
    public DmcCsunBodySensorVo getCsunBodySensorByDeviceId(Long deviceId) {

        CsunBodySensorPageQuery csunBodySensorPageQuery = new CsunBodySensorPageQuery();
        csunBodySensorPageQuery.setDeviceId(deviceId);
        csunBodySensorPageQuery.setDeviceType(DmcDeviceTypeEnum.CSUN_BODY_SENSOR.getIndex());

        PageHelper.startPage(1, 1);

        List<DmcCsunBodySensorVo> dmcCsunBodySensorVoList = dmcCsunBodySensorLocationMapper
                .queryGroupBodySensorListWithPage(csunBodySensorPageQuery);

        if (PublicUtil.isEmpty(dmcCsunBodySensorVoList)) {
            return null;
        }

        return dmcCsunBodySensorVoList.get(0);
    }

    /**
     * get csun body sensor by device id
     *
     * @param deviceNo device no
     * @return dmc csun body sensor vo
     */
    @Override
    public DmcCsunBodySensorVo getCsunBodySensorByDeviceNo(String deviceNo) {

        CsunBodySensorPageQuery csunBodySensorPageQuery = new CsunBodySensorPageQuery();
        csunBodySensorPageQuery.setDeviceNo(deviceNo);
        // csunBodySensorPageQuery.setDeviceType(DmcDeviceTypeEnum.NEWBODY.getIndex());

        PageHelper.startPage(1, 1);

        /*
        * 2020-01-14
        * 原方法中deviceNo是模糊搜索，导致查询的设备不对，编写新方法，不使用模糊查询
        * */
/*
        List<DmcCsunBodySensorVo> dmcCsunBodySensorVoList = dmcCsunBodySensorLocationMapper
                .queryGroupBodySensorListWithPage(csunBodySensorPageQuery);
*/

        List<DmcCsunBodySensorVo> dmcCsunBodySensorVoList = dmcCsunBodySensorLocationMapper
                .getCsunBodySensorByDeviceNo(csunBodySensorPageQuery);

        if (PublicUtil.isEmpty(dmcCsunBodySensorVoList)) {
            return null;
        }

        return dmcCsunBodySensorVoList.get(0);
    }

    /**
     * get csun body sensor by room id
     *
     * @param roomId room id
     * @return the list.
     */
    @Override
    public List<DmcCsunBodySensorVo> getCsunBodySensorByRoomId(Long roomId) {


        CsunBodySensorPageQuery csunBodySensorPageQuery = new CsunBodySensorPageQuery();
        csunBodySensorPageQuery.setRoomId(roomId);
        csunBodySensorPageQuery.setDeviceType(DmcDeviceTypeEnum.CSUN_BODY_SENSOR.getIndex());

        List<DmcCsunBodySensorVo> dmcCsunBodySensorVoList = dmcCsunBodySensorLocationMapper
                .queryGroupBodySensorListWithPage(csunBodySensorPageQuery);


        return dmcCsunBodySensorVoList;

    }

    /**
     * delete body sensor by id
     *
     * @param id id
     * @return the int.
     */
    @Override
    public Integer deleteBodySensorById(Long id) {

        // 1.判断设备Id是否存在
        DmcDevice dmcDevice = dmcDeviceService.checkDeviceIsCsunBodySensorByDeviceId(id);
        if (PublicUtil.isEmpty(dmcDevice)) {
            throw new DmcBizException(ErrorCodeEnum.DMC100610027, id);
        }

        // 2.判断人体感应是否已经绑定
        DmcCsunBodySensorLocation dmcCsunBodySensorLocationQuery = dmcCsunBodySensorLocationMapper
                .selectByPrimaryKey(id);
        if (PublicUtil.isNotEmpty(dmcCsunBodySensorLocationQuery)) {
            dmcCsunBodySensorLocationMapper.deleteByPrimaryKey(id);
        }

        // 判断是绑定了网关
        DmcCsunGatewayBind dmcCsunGatewayBind = new DmcCsunGatewayBind();
        dmcCsunGatewayBind.setDeviceId(id);
        int count = dmcCsunGatewayBindService.selectCount(dmcCsunGatewayBind);
        if (count > 0) {
            throw new DmcBizException(ErrorCodeEnum.DMC100614009);
        }

        // 判断是否绑定了人感组
        DmcCsunBodyGroupBind dmcCsunBodyGroupBind = new DmcCsunBodyGroupBind();
        dmcCsunBodyGroupBind.setDeviceId(id);
        count = dmcCsunBodyGroupBindService.selectCount(dmcCsunBodyGroupBind);
        if (count > 0) {
            throw new DmcBizException(ErrorCodeEnum.DMC100614011);
        }

        // 3.删除设备
        return dmcDeviceService.deleteDmcDeviceById(id);
    }
    @Override
    public Map<String, Object> getRecentData(Integer oldmanId) {
        return dmcCsunBodySensorLocationMapper.getRecentData(oldmanId);
    }

    /**
     * query body sensor location by room id list
     *
     * @param roomIdList room id list
     *
     * @return the list.
     */
    @Override
    public List<BodySensorReqVo> queryBodySensorLocationByRoomIds(List<Integer> roomIdList) {

        return dmcCsunBodySensorLocationMapper.queryBodySensorLocationByRoomIds(roomIdList);
    }

    @Override
    public DmcDeviceByRoom selectRoomIdByDeviceId(Long alertId) {

        return dmcCsunBodySensorLocationMapper.selectRoomIdByDeviceId(alertId);
    }

    @Override
    public List<PropertyDataVo> selectDeviceData(SelectDeviceDataDto selectDeviceDataDto) {
        return dmcCsunBodySensorLocationMapper.selectDeviceData(selectDeviceDataDto);
    }
}
